import userService from "../service/user.service.js";
import jwt from "jsonwebtoken";
import fse from "fs-extra";
import path from "path";
import bcrypt from "bcryptjs";
import multer from "multer";
import configer from "../utils/configer.js";

import "express-async-errors";

const AVATAR_UPLOAD_DIR = path.resolve("uploads", "avatar");
const PASSWORD_HASH_SALT = 10;
const AVATAR_SIZE_LIMIT = 10 * 1024 * 1024; // 10MB

const register = async (req, res) => {
  const { username, password } = req.body;

  const existingUser = await userService.getUserByUsername(username);
  if (existingUser) {
    return res.status(400).json({ message: "用户名已存在" });
  }

  const hashedPassword = await bcrypt.hash(password, PASSWORD_HASH_SALT);
  const defaultSpace = configer.get("defaultUserSpace");

  const user = await userService.createUser(username, hashedPassword, defaultSpace * 1024 * 1024);
  const token = jwt.sign(
    { id: user.id, username: user.username },
    process.env.JWT_SECRET,
    { expiresIn: process.env.TOKEN_EXPIRES_IN },
  );
  delete user.password;
  res.status(201).json({ message: "注册成功", user, token });
};

const login = async (req, res) => {
  const { username, password } = req.body;
  const user = await userService.getUserByUsername(username);
  if (!user) {
    return res.status(400).json({ message: "用户名或密码错误" });
  }
  if (user.status == 'SUSPENDED') {
    return res.status(400).json({ message: "用户已被冻结" });
  }
  const isMatch = await bcrypt.compare(password, user.password);
  if (!isMatch) {
    return res.status(400).json({ message: "用户名或密码错误" });
  }
  const token = jwt.sign(
    { id: user.id, username: user.username },
    process.env.JWT_SECRET,
    { expiresIn: process.env.TOKEN_EXPIRES_IN },
  );
  delete user.password;

  const ipAddress = req.headers["x-forwarded-for"] || req.socket.remoteAddress;
  const ip = ipAddress.split(",")[0].trim();
  const lastLogin = new Date();
  await userService.updateUser(user.id, { lastLogin, ip });

  res.status(200).json({ message: "登录成功", user, token });
};

const getUserInfo = async (req, res) => {
  const userId = req.user.id;
  const user = await userService.getUserById(userId);
  delete user.password;

  if (!user) {
    return res.status(404).json({ message: "用户不存在" });
  }

  const token = jwt.sign(
    { id: user.id, username: user.username },
    process.env.JWT_SECRET,
    { expiresIn: process.env.TOKEN_EXPIRES_IN },
  );
  res.status(200).json({ message: "获取用户信息成功", user, token });
};

// 上传头像
const storage = multer.diskStorage({
  destination: (req, file, cb) => cb(null, AVATAR_UPLOAD_DIR),
  filename: (req, file, cb) => {
    cb(null, req.user.id + path.extname(file.originalname).toLowerCase());
  },
});

const fileFilter = (req, file, cb) => {
  const ext = path.extname(file.originalname).toLowerCase().replace(".", "");
  if (["jpg", "jpeg", "png", "gif", "webp"].includes(ext)) {
    cb(null, true);
  } else {
    const error = new Error("仅允许上传 JPG/JPEG/PNG/GIF/WEBP 格式的图片");
    error.code = "INVALID_FILE_TYPE";
    cb(error, false);
  }
};

const upload = multer(
  { storage, limits: { fileSize: AVATAR_SIZE_LIMIT, files: 1 } },
  fileFilter,
).single("file");

const uploadAvatar = async (req, res) => {
  upload(req, res, (err) => {
    if (err) {
      let message = "文件上传失败";
      if (err.code === "LIMIT_FILE_SIZE") {
        message = `文件大小超过 ${AVATAR_SIZE_LIMIT / 1024 / 1024}MB 限制`;
      } else if (err.code === "INVALID_FILE_TYPE") {
        message = err.message;
      } else if (err.code === "LIMIT_UNEXPECTED_FILE") {
        message = "只能上传一个文件";
      }
      return res.status(400).json({ message });
    }

    if (!req.file) {
      return res.status(400).json({ message: "没有文件上传" });
    }
    // 上传成功
    res.status(201).json({ message: "头像上传成功" });
  });
};

const getAvatar = async (req, res) => {
  const userId = req.params.id;
  const files = fse.readdirSync(AVATAR_UPLOAD_DIR);
  let avatarFile = files.find((file) => file.startsWith(userId));

  if (!avatarFile) {
    avatarFile = "default.png";
  }

  const filePath = path.join(AVATAR_UPLOAD_DIR, avatarFile);
  const mimeType = getMimeType(avatarFile);

  res.setHeader("Content-Type", mimeType);
  fse.createReadStream(filePath).pipe(res);
};

function getMimeType(filename) {
  const ext = path.extname(filename).toLowerCase();
  const mimeTypes = {
    ".jpg": "image/jpeg",
    ".jpeg": "image/jpeg",
    ".png": "image/png",
    ".gif": "image/gif",
    ".webp": "image/webp",
  };
  return mimeTypes[ext] || "application/octet-stream";
}

const updateUser = async (req, res) => {
  const userId = req.user.id;
  const updates = req.body;

  if (updates.username === req.user.username) {
    return res.status(400).json({ message: "新用户名和原用户名相同" });
  }
  const existingUser = await userService.getUserByUsername(updates.username);
  if (existingUser) {
    return res.status(400).json({ message: "用户名已存在" });
  }
  const user = await userService.updateUser(userId, updates);

  const token = jwt.sign(
    { id: user.id, username: user.username },
    process.env.JWT_SECRET,
    { expiresIn: process.env.TOKEN_EXPIRES_IN },
  );
  delete user.password;
  res.status(200).json({ message: "更新成功", user, token });
};

const updatePassword = async (req, res) => {
  const userId = req.user.id;
  const oldpassword = req.body.oldpassword;
  const newpassword = req.body.newpassword;

  const olduser = await userService.getUserById(userId);
  const isMatch = bcrypt.compare(oldpassword, olduser?.password);
  if (!olduser || !isMatch) {
    return res.status(400).json({ message: "原密码不正确" });
  }

  const hashedPassword = await bcrypt.hash(newpassword, PASSWORD_HASH_SALT);
  await userService.updateUser(userId, { password: hashedPassword });
  res.status(200).json({ message: "更新成功" });
};

export default {
  register,
  login,
  upload,
  uploadAvatar,
  getAvatar,
  updateUser,
  updatePassword,
  getUserInfo,
};
